<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type"
        content="text/html; charset=ISO-8859-1" />
  <title>Code Examples for Programming in Scala</title>
  <link rel="stylesheet" href="style.css" type="text/css"/>
</head>
<body>

<div id="mainTitles"><h3>Code Examples for</h3><h2>Programming in Scala</h2></div>  <p><a href="../index.html">
    Return to chapter index
  </a></p>
  <h2>18 Stateful Objects</h2>

  <p><a href="../stateful-objects/transcript.txt">
    Sample run of chapter's interpreter examples
  </a></p>

  <ul>

    <li>18.1 <a href="#sec1">What makes an object stateful?</a></li>
    <li>18.2 <a href="#sec2">Reassignable variables and properties</a></li>
    <li>18.3 <a href="#sec3">Case study: Discrete event simulation</a></li>
    <li>18.4 <a href="#sec4">A language for digital circuits</a></li>
    <li>18.5 <a href="#sec5">The <span class="mono">Simulation</span> API</a></li>
    <li>18.6 <a href="#sec6">Circuit Simulation</a></li>
    <li>18.7 <a href="#sec7">Conclusion</a></li>
  </ul>

  <h3><a name="sec1"></a>18.1 What makes an object stateful?</h3>

  <pre><hr>
// In file <a href="../stateful-objects/Ex1.scala">stateful-objects/Ex1.scala</a>

  val cs = List('a', 'b', 'c')

<hr>
// In file <a href="../stateful-objects/Ex2.scala">stateful-objects/Ex2.scala</a>

  class BankAccount {

    private var bal: Int = 0

    def balance: Int = bal

    def deposit(amount: Int) {
      require(amount &gt; 0)
      bal += amount
    }

    def withdraw(amount: Int): Boolean = 
      if (amount &gt; bal) false
      else {
        bal -= amount
        true
      }
  } 

<hr>
  scala&gt; val account = new BankAccount
<span class="output">  account: BankAccount = BankAccount@bf5bb7</span>

  scala&gt; account deposit 100

  scala&gt; account withdraw 80
<span class="output">  res1: Boolean = true</span>

  scala&gt;  account withdraw 80
<span class="output">  res2: Boolean = false</span>

<hr>
// In file <a href="../stateful-objects/Ex3.scala">stateful-objects/Ex3.scala</a>

  class Keyed {
    def computeKey: Int = ... // this will take some time
    ...
  }

<hr>
// In file <a href="../stateful-objects/Ex3.scala">stateful-objects/Ex3.scala</a>

  class MemoKeyed extends Keyed {
    private var keyCache: Option[Int] = None
    override def computeKey: Int = {
      if (!keyCache.isDefined) keyCache = Some(super.computeKey)
      keyCache.get
    }
  }

<hr>
  </pre>
  <h3><a name="sec2"></a>18.2 Reassignable variables and properties</h3>

  <pre><hr>
  var hour = 12

<hr>
// In file <a href="../stateful-objects/Ex4.scala">stateful-objects/Ex4.scala</a>

  class Time {
    var hour = 12
    var minute = 0
  }

<hr>
// In file <a href="../stateful-objects/Ex5.scala">stateful-objects/Ex5.scala</a>

  class Time {

    private[this] var h = 12
    private[this] var m = 0

    def hour: Int = h
    def hour_=(x: Int) { h = x }

    def minute: Int = m
    def minute_=(x: Int) { m = x }
  } 

<hr>
// In file <a href="../stateful-objects/Ex6.scala">stateful-objects/Ex6.scala</a>

  class Time {

    private[this] var h = 12
    private[this] var m = 12

    def hour: Int = h
    def hour_= (x: Int) {
      require(0 &lt;= x &amp;&amp; x &lt; 24)
      h = x
    }

    def minute = m
    def minute_= (x: Int) {
      require(0 &lt;= x &amp;&amp; x &lt; 60)
      m = x
    }
  } 

<hr>
// In file <a href="../stateful-objects/Ex7.scala">stateful-objects/Ex7.scala</a>

  class Thermometer {

    var celsius: Float = _

    def fahrenheit = celsius * 9 / 5 + 32
    def fahrenheit_= (f: Float) {
      celsius = (f - 32) * 5 / 9
    }
    override def toString = fahrenheit +"F/"+ celsius +"C"
  }

<hr>
  var celsius: Float

<hr>
  scala&gt; val t = new Thermometer
<span class="output">  t: Thermometer = 32.0F/0.0C</span>

  scala&gt; t.celsius = 100

  scala&gt; t
<span class="output">  res3: Thermometer = 212.0F/100.0C</span>

  scala&gt; t.fahrenheit = -40

  scala&gt; t
<span class="output">  res4: Thermometer = -40.0F/-40.0C</span>

<hr>
  </pre>
  <h3><a name="sec3"></a>18.3 Case study: Discrete event simulation</h3>

  <h3><a name="sec4"></a>18.4 A language for digital circuits</h3>

  <pre><hr>
  val a = new Wire
  val b = new Wire
  val c = new Wire

<hr>
  val a, b, c = new Wire

<hr>
  def inverter(input: Wire, output: Wire)
  def andGate(a1: Wire, a2: Wire, output: Wire)
  def orGate(o1: Wire, o2: Wire, output: Wire)

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def halfAdder(a: Wire, b: Wire, s: Wire, c: Wire) {
    val d, e = new Wire
    orGate(a, b, d)
    andGate(a, b, c)
    inverter(c, e)
    andGate(d, e, s)
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def fullAdder(a: Wire, b: Wire, cin: Wire,
      sum: Wire, cout: Wire) {

    val s, c1, c2 = new Wire
    halfAdder(a, cin, s, c1)
    halfAdder(b, s, sum, c2)
    orGate(c1, c2, cout)
  }

<hr>
  </pre>
  <h3><a name="sec5"></a>18.5 The <span class="mono">Simulation</span> API</h3>

  <pre><hr>
// In file <a href="../stateful-objects/Simulator1.scala">stateful-objects/Simulator1.scala</a>

  abstract class Simulation {

    type Action = () =&gt; Unit

    case class WorkItem(time: Int, action: Action)

    private var curtime = 0
    def currentTime: Int = curtime

    private var agenda: List[WorkItem] = List()

    private def insert(ag: List[WorkItem],
        item: WorkItem): List[WorkItem] = {

      if (ag.isEmpty || item.time &lt; ag.head.time) item :: ag
      else ag.head :: insert(ag.tail, item)
    }

    def afterDelay(delay: Int)(block: =&gt; Unit) {
      val item = WorkItem(currentTime + delay, () =&gt; block)
      agenda = insert(agenda, item)
    }

    private def next() {
      (agenda: @unchecked) match {
        case item :: rest =&gt; 
          agenda = rest 
          curtime = item.time
          item.action()
      }
    }

    def run() {
      afterDelay(0) {
        println("*** simulation started, time = "+
            currentTime +" ***")
      }
      while (!agenda.isEmpty) next()
    }
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  type Action = () =&gt; Unit

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  private var curtime: Int = 0

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def currentTime: Int = curtime

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  case class WorkItem(time: Int, action: Action)

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  private var agenda: List[WorkItem] = List()

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def afterDelay(delay: Int)(block: =&gt; Unit) {
    val item = WorkItem(currentTime + delay, () =&gt; block)
    agenda = insert(agenda, item)
  }

<hr>
  afterDelay(delay) { count += 1 }

<hr>
// In file <a href="../concurrency/ParallelSimulation.scala">concurrency/ParallelSimulation.scala</a>

  private def insert(ag: List[WorkItem], 
      item: WorkItem): List[WorkItem] =  {

    if (ag.isEmpty || item.time &lt; ag.head.time) item :: ag
    else ag.head :: insert(ag.tail, item)
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def run() {
    afterDelay(0) {
      println("*** simulation started, time = "+
          currentTime +" ***")
    }
    while (!agenda.isEmpty) next()
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  private def next() {
    (agenda: @unchecked) match {
      case item :: rest =&gt; 
        agenda = rest 
        curtime = item.time
        item.action()
    }
  }

<hr>
<span class="output">  Simulator.scala:19: warning: match is not exhaustive!</span>
<span class="output">  missing combination            Nil</span>
<span class="output"></span>
<span class="output">      agenda match {</span>
<span class="output">      ^</span>
<span class="output">  one warning found</span>

<hr>
  </pre>
  <h3><a name="sec6"></a>18.6 Circuit Simulation</h3>

  <pre><hr>
// In file <a href="../stateful-objects/Simulator1.scala">stateful-objects/Simulator1.scala</a>

  package org.stairwaybook.simulation

  abstract class BasicCircuitSimulation extends Simulation {

    def InverterDelay: Int
    def AndGateDelay: Int
    def OrGateDelay: Int

    class Wire {

      private var sigVal = false
      private var actions: List[Action] = List()

      def getSignal = sigVal

      def setSignal(s: Boolean) = 
        if (s != sigVal) {
          sigVal = s
          actions foreach (_ ()) 
        }

      def addAction(a: Action) = {
        actions = a :: actions
        a()
      }
    }

    def inverter(input: Wire, output: Wire) = {
      def invertAction() {
        val inputSig = input.getSignal
        afterDelay(InverterDelay) {
          output setSignal !inputSig 
        }
      }
      input addAction invertAction
    }

    // continued in Listing 18.10...

<hr>
// In file <a href="../stateful-objects/Simulator1.scala">stateful-objects/Simulator1.scala</a>

    // ...continued from Listing 18.9
    def andGate(a1: Wire, a2: Wire, output: Wire) = {
      def andAction() = {
        val a1Sig = a1.getSignal
        val a2Sig = a2.getSignal
        afterDelay(AndGateDelay) {
          output setSignal (a1Sig &amp; a2Sig) 
        }
      }
      a1 addAction andAction
      a2 addAction andAction
    }

    def orGate(o1: Wire, o2: Wire, output: Wire) {
      def orAction() {
        val o1Sig = o1.getSignal
        val o2Sig = o2.getSignal
        afterDelay(OrGateDelay) {
          output setSignal (o1Sig | o2Sig)
        }
      }
      o1 addAction orAction
      o2 addAction orAction
    }

    def probe(name: String, wire: Wire) {
      def probeAction() {
        println(name +" "+ currentTime +
            " new-value = "+ wire.getSignal)
      }
      wire addAction probeAction
    }
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  class Wire {

    private var sigVal = false
    private var actions: List[Action] = List()

    def getSignal = sigVal

    def setSignal(s: Boolean) = 
      if (s != sigVal) {
        sigVal = s
        actions foreach (_ ()) 
      }

    def addAction(a: Action) = {
      actions = a :: actions
      a()
    }
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def inverter(input: Wire, output: Wire) = {
    def invertAction() {
      val inputSig = input.getSignal
      afterDelay(InverterDelay) {
        output setSignal !inputSig 
      }
    }
    input addAction invertAction
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def andGate(a1: Wire, a2: Wire, output: Wire) = {
    def andAction() = {
      val a1Sig = a1.getSignal
      val a2Sig = a2.getSignal
      afterDelay(AndGateDelay) {
        output setSignal (a1Sig &amp; a2Sig) 
      }
    }
    a1 addAction andAction
    a2 addAction andAction
  }

<hr>
// In file <a href="../stateful-objects/Simulator2.scala">stateful-objects/Simulator2.scala</a>

  def probe(name: String, wire: Wire) {
    def probeAction() {
      println(name +" "+ currentTime +
          " new-value = "+ wire.getSignal)
    }
    wire addAction probeAction
  }

<hr>
// In file <a href="../stateful-objects/Simulator1.scala">stateful-objects/Simulator1.scala</a>

  package org.stairwaybook.simulation

  abstract class CircuitSimulation
    extends BasicCircuitSimulation {

    def halfAdder(a: Wire, b: Wire, s: Wire, c: Wire) {
      val d, e = new Wire
      orGate(a, b, d)
      andGate(a, b, c)
      inverter(c, e)
      andGate(d, e, s)
    }

    def fullAdder(a: Wire, b: Wire, cin: Wire,
        sum: Wire, cout: Wire) {

      val s, c1, c2 = new Wire
      halfAdder(a, cin, s, c1)
      halfAdder(b, s, sum, c2)
      orGate(c1, c2, cout)
    }
  }

<hr>
  scala&gt; import org.stairwaybook.simulation._
<span class="output">  import org.stairwaybook.simulation._</span>

<hr>
  scala&gt; object MySimulation extends CircuitSimulation {
       |   def InverterDelay = 1
       |   def AndGateDelay = 3
       |   def OrGateDelay = 5
       | }
<span class="output">  defined module MySimulation</span>

<hr>
  scala&gt; import MySimulation._
<span class="output">  import MySimulation._</span>

<hr>
  scala&gt; val input1, input2, sum, carry = new Wire
<span class="output">  input1: MySimulation.Wire =</span>
<span class="output">      simulator.BasicCircuitSimulation$Wire@111089b</span>
<span class="output">  input2: MySimulation.Wire =</span>
<span class="output">      simulator.BasicCircuitSimulation$Wire@14c352e</span>
<span class="output">  sum: MySimulation.Wire =</span>
<span class="output">      simulator.BasicCircuitSimulation$Wire@37a04c</span>
<span class="output">  carry: MySimulation.Wire =</span>
<span class="output">      simulator.BasicCircuitSimulation$Wire@1fd10fa</span>

  scala&gt; probe("sum", sum)
<span class="output">  sum 0 new-value = false</span>

  scala&gt; probe("carry", carry)
<span class="output">  carry 0 new-value = false</span>

<hr>
  scala&gt; halfAdder(input1, input2, sum, carry)

<hr>
  scala&gt; input1 setSignal true

  scala&gt; run()
<span class="output">  *** simulation started, time = 0 ***</span>
<span class="output">  sum 8 new-value = true</span>

  scala&gt; input2 setSignal true

  scala&gt; run()
<span class="output">  *** simulation started, time = 8 ***</span>
<span class="output">  carry 11 new-value = true</span>
<span class="output">  sum 15 new-value = false</span>

<hr>
  </pre>
  <h3><a name="sec7"></a>18.7 Conclusion</h3>


 <table>
 <tr valign="top">
 <td>
 <div id="moreinfo">
 <p>
 For more information about <em>Programming in Scala</em> (the "Stairway Book"), please visit:
 </p>
 
 <p>
 <a href="http://www.artima.com/shop/programming_in_scala">http://www.artima.com/shop/programming_in_scala</a>
 </p>
 
 <p>
 and:
 </p>
 
 <p>
 <a href="http://booksites.artima.com/programming_in_scala">http://booksites.artima.com/programming_in_scala</a>
 </p>
 </div>
 </td>
 <td>
 <div id="license">
 <p>
   Copyright &copy; 2007-2008 Artima, Inc. All rights reserved.
 </p>

 <p>
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
 </p>

 <p style="margin-left: 20px">
   <a href="http://www.apache.org/licenses/LICENSE-2.0">
     http://www.apache.org/licenses/LICENSE-2.0
   </a>
 </p>

 <p>
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 </p>
 </div>
 </td>
 </tr>
 </table>

</body>
</html>
